home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / util / recover.c < prev   
C/C++ Source or Header  |  1993-01-21  |  6KB  |  278 lines

  1. /* recover.c - NetHack version 3.1 */
  2.  
  3. /*
  4.  *  Utility for reconstructing NetHack save file from a set of individual
  5.  *  level files.  Requires that the `checkpoint' option be enabled at the
  6.  *  time NetHack creates those level files.
  7.  */
  8. #include "config.h"
  9. #if !defined(O_WRONLY) && !defined(LSC) && !defined(AZTEC_C)
  10. #include <fcntl.h>
  11. #endif
  12.  
  13. #ifndef VMS
  14. # ifdef exit
  15. #  undef exit
  16. # endif
  17. #ifdef MICRO
  18. extern void FDECL(exit, (int));
  19. #endif
  20. #else    /* VMS */
  21. extern int FDECL(vms_creat, (const char *,unsigned));
  22. extern int FDECL(vms_open, (const char *,int,unsigned));
  23. #endif    /* VMS */
  24.  
  25. int FDECL(restore_savefile, (char *));
  26. void FDECL(set_levelfile_name, (int));
  27. int FDECL(open_levelfile, (int));
  28. int FDECL(create_savefile, (char *));
  29. void FDECL(copy_bytes, (int,int));
  30.  
  31. #ifdef UNIX
  32. #define SAVESIZE    (PL_NSIZ + 13)    /* save/99999player.e */
  33. #else
  34. # ifdef VMS
  35. #define SAVESIZE    (PL_NSIZ + 22)    /* [.save]<uid>player.e;1 */
  36. # else
  37. #define SAVESIZE    FILENAME    /* from macconf.h or pcconf.h */
  38. # endif
  39. #endif
  40.  
  41. char savename[SAVESIZE]; /* holds relative path of save file from playground */
  42.  
  43.  
  44. int
  45. main(argc, argv)
  46. int argc;
  47. char *argv[];
  48. {
  49.     int argno;
  50.     char *dir = (char *)0;
  51.  
  52.     if (argc == 1 || (argc == 2 && !strcmp(argv[1], "-"))) {
  53.         (void) fprintf(stderr,
  54.                 "Usage: %s [-d directory] base1 base2 ...\n",
  55.                 argv[0]);
  56.         exit(1);
  57.     }
  58.  
  59.     argno = 1;
  60.     if (!strncmp(argv[argno], "-d", 2)) {
  61.         dir = argv[argno]+2;
  62.         if (*dir == '=' || *dir == ':') dir++;
  63.         if (!*dir && argc > argno) {
  64.             argno++;
  65.             dir = argv[argno];
  66.         }
  67.         if (!*dir) {
  68.             (void) fprintf(stderr,
  69.             "%s: flag -d must be followed by a directory name.\n",
  70.             argv[0]);
  71.             exit(1);
  72.         }
  73.         argno++;
  74.     }
  75.  
  76.     if (!dir) dir = getenv("NETHACKDIR");
  77.     if (!dir) dir = getenv("HACKDIR");
  78. #if defined(SECURE) && !defined(VMS)
  79.     if (dir
  80. # ifdef HACKDIR
  81.         && strcmp(dir, HACKDIR)
  82. # endif
  83.         ) {
  84.         (void) setgid(getgid());
  85.         (void) setuid(getuid());
  86.     }
  87. #endif    /* SECURE && !VMS */
  88.  
  89. #ifdef HACKDIR
  90.     if (!dir) dir = HACKDIR;
  91. #endif
  92.  
  93.     if (dir && chdir(dir) < 0) {
  94.         (void) fprintf(stderr, "%s: cannot chdir to %s.\n",
  95.                 argv[0], dir);
  96.         exit(1);
  97.     }
  98.  
  99.     while (argc > argno) {
  100.         (void) restore_savefile(argv[argno]);
  101.         argno++;
  102.     }
  103. #ifndef VMS
  104.     return 0;
  105. #else
  106.     return 1;       /* vms success */
  107. #endif /*VMS*/
  108. }
  109.  
  110. static char lock[256];
  111.  
  112. void
  113. set_levelfile_name(lev)
  114. int lev;
  115. {
  116.     char *tf;
  117.  
  118.     tf = rindex(lock, '.');
  119.     if (!tf) {
  120.         tf = lock;
  121.         while (*tf) tf++;
  122.     }
  123. #ifdef VMS
  124.     (void) sprintf(tf, ".%d;1", lev);
  125. #else
  126.     (void) sprintf(tf, ".%d", lev);
  127. #endif
  128. }
  129.  
  130. int
  131. open_levelfile(lev)
  132. int lev;
  133. {
  134.     int fd;
  135.  
  136.     set_levelfile_name(lev);
  137. #ifdef MICRO
  138.     fd = open(lock, O_RDONLY | O_BINARY);
  139. #else
  140.     fd = open(lock, O_RDONLY, 0);
  141. #endif
  142.     return fd;
  143. }
  144.  
  145. int
  146. create_savefile(savename)
  147. char *savename;
  148. {
  149.     int fd;
  150.  
  151. #ifdef MICRO
  152.     fd = open(savename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  153. #else
  154.     fd = creat(savename, FCMASK);
  155. #endif
  156.     return fd;
  157. }
  158.  
  159. void
  160. copy_bytes(ifd, ofd)
  161. int ifd, ofd;
  162. {
  163.     char buf[BUFSIZ];
  164.     int nfrom, nto;
  165.  
  166.     do {
  167.         nfrom = read(ifd, buf, BUFSIZ);
  168.         nto = write(ofd, buf, nfrom);
  169.         if (nto != nfrom) {
  170.             (void) fprintf(stderr, "file copy failed!\n");
  171.             exit(1);
  172.         }
  173.     } while (nfrom == BUFSIZ);
  174. }
  175.  
  176. int
  177. restore_savefile(basename)
  178. char *basename;
  179. {
  180.     int gfd, lfd, sfd;
  181.     int lev, savelev, hpid;
  182.     xchar levc;
  183.  
  184.     /* level 0 file contains:
  185.      *    pid of creating process (ignored here)
  186.      *    level number for current level of save file
  187.      *    name of save file nethack would have created
  188.      *    and game state
  189.      */
  190.     (void) strcpy(lock, basename);
  191.     gfd = open_levelfile(0);
  192.     if (gfd < 0) {
  193.         (void) fprintf(stderr, "Cannot open level 0 for %s.\n", basename);
  194.         return(-1);
  195.     }
  196.     (void) read(gfd, (genericptr_t) &hpid, sizeof(hpid));
  197.     if (read(gfd, (genericptr_t) &savelev, sizeof(savelev))
  198.                             != sizeof(savelev)) {
  199.         (void) fprintf(stderr,
  200.         "Checkpointing was not in effect for %s -- recovery impossible.\n",
  201.         basename);
  202.         (void) close(gfd);
  203.         return(-1);
  204.     }
  205.     (void) read(gfd, (genericptr_t) savename, sizeof(savename));
  206.  
  207.     /* save file should contain:
  208.      *    current level (including pets)
  209.      *    (non-level-based) game state
  210.      *    other levels
  211.      */
  212.     sfd = create_savefile(savename);
  213.     if (sfd < 0) {
  214.         (void) fprintf(stderr, "Cannot create savefile %s.\n", savename);
  215.         (void) close(gfd);
  216.         return(-1);
  217.     }
  218.  
  219.     lfd = open_levelfile(savelev);
  220.     if (lfd < 0) {
  221.         (void) fprintf(stderr, "Cannot open level of save for %s.\n",
  222.                 basename);
  223.         (void) close(gfd);
  224.         (void) close(sfd);
  225.         return(-1);
  226.     }
  227.  
  228.     copy_bytes(lfd, sfd);
  229.     (void) close(lfd);
  230.     (void) unlink(lock);
  231.  
  232.     copy_bytes(gfd, sfd);
  233.     (void) close(gfd);
  234.     set_levelfile_name(0);
  235.     (void) unlink(lock);
  236.  
  237.     for (lev = 1; lev < 256; lev++) {
  238.         /* level numbers are kept in xchars in save.c, so the
  239.          * maximum level number (for the endlevel) must be < 256
  240.          */
  241.         if (lev != savelev) {
  242.             lfd = open_levelfile(lev);
  243.             if (lfd >= 0) {
  244.                 /* any or all of these may not exist */
  245.                 levc = (xchar) lev;
  246.                 write(sfd, (genericptr_t) &levc, sizeof(levc));
  247.                 copy_bytes(lfd, sfd);
  248.                 (void) close(lfd);
  249.                 (void) unlink(lock);
  250.             }
  251.         }
  252.     }
  253.  
  254.     (void) close(sfd);
  255.  
  256. #ifdef AMIGA
  257.             /* we need to create an icon for the saved game
  258.              * or HackWB won't notice the file.
  259.              */
  260.     {
  261.     char iconfile[FILENAME];
  262.     int in, out;
  263.  
  264.     sprintf(iconfile,"%s.info",savename);
  265.     in=open("NetHack:default.icon",O_RDONLY);
  266.     out=open(iconfile,O_WRONLY | O_TRUNC | O_CREAT);
  267.     if(in > -1 && out > -1){
  268.         copy_bytes(in,out);
  269.     }
  270.     if(in > -1)close(in);
  271.     if(out > -1)close(out);
  272.     }
  273. #endif
  274.     return(0);
  275. }
  276.  
  277. /*recover.c*/
  278.